{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "        if (window._pyforest_update_imports_cell) { window._pyforest_update_imports_cell('import pandas as pd'); }\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>User ID</th>\n",
       "      <th>Gender</th>\n",
       "      <th>Age</th>\n",
       "      <th>EstimatedSalary</th>\n",
       "      <th>Purchased</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>15624510</td>\n",
       "      <td>Male</td>\n",
       "      <td>19</td>\n",
       "      <td>19000</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>15810944</td>\n",
       "      <td>Male</td>\n",
       "      <td>35</td>\n",
       "      <td>20000</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>15668575</td>\n",
       "      <td>Female</td>\n",
       "      <td>26</td>\n",
       "      <td>43000</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>15603246</td>\n",
       "      <td>Female</td>\n",
       "      <td>27</td>\n",
       "      <td>57000</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>15804002</td>\n",
       "      <td>Male</td>\n",
       "      <td>19</td>\n",
       "      <td>76000</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    User ID  Gender  Age  EstimatedSalary  Purchased\n",
       "0  15624510    Male   19            19000          0\n",
       "1  15810944    Male   35            20000          0\n",
       "2  15668575  Female   26            43000          0\n",
       "3  15603246  Female   27            57000          0\n",
       "4  15804002    Male   19            76000          0"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv('Social_Network_Ads.csv')\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = df.iloc[:,2:4]\n",
    "y = df.iloc[:,4:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.25,random_state=0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Standardization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "sc = StandardScaler()\n",
    "X_train = sc.fit_transform(X_train)\n",
    "X_test = sc.transform(X_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Timer:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "def timer(start_time=None):\n",
    "    if not start_time:\n",
    "        start_time = datetime.now()\n",
    "        return start_time\n",
    "    elif start_time:\n",
    "        thour, temp_sec = divmod((datetime.now() - start_time).total_seconds(), 3600)\n",
    "        tmin, tsec = divmod(temp_sec, 60)\n",
    "        print('\\n Time taken: %i hours %i minutes and %s seconds.' % (thour, tmin, round(tsec, 2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h3>Applying Random Forest</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.ensemble import RandomForestClassifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='entropy',\n",
       "                       max_depth=None, max_features='auto', max_leaf_nodes=None,\n",
       "                       min_impurity_decrease=0.0, min_impurity_split=None,\n",
       "                       min_samples_leaf=1, min_samples_split=2,\n",
       "                       min_weight_fraction_leaf=0.0, n_estimators=10,\n",
       "                       n_jobs=None, oob_score=False, random_state=50, verbose=0,\n",
       "                       warm_start=False)"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "classifier = RandomForestClassifier(n_estimators=10,criterion='entropy',random_state=50)\n",
    "classifier.fit(X_train,y_train.values.ravel())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = classifier.predict(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import confusion_matrix\n",
    "cm  = confusion_matrix(y_test,y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.92"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "accuracy = accuracy_score(y_test,y_pred)\n",
    "accuracy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can also check with cross_val_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import cross_val_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "score = cross_val_score(classifier,X,y.values.ravel(),cv=10,scoring='accuracy').mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.87494684177611"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we will work with RandomizedSearchCV to find the best parameters"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import RandomizedSearchCV\n",
    "from scipy.stats import randint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [],
   "source": [
    "est = RandomForestClassifier(n_jobs=-1)\n",
    "rf_p_dist={'max_depth':[3,5,10,None],\n",
    "              'n_estimators':[10,100,200,300,400,500],\n",
    "              'max_features':randint(1,3),\n",
    "               'criterion':['gini','entropy'],\n",
    "               'bootstrap':[True,False],\n",
    "               'min_samples_leaf':randint(1,4),\n",
    "              }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Use this function if you wanna execute via function otherwise use the variable\n",
    "# def hypertuning_rscv(est, p_distr, nbr_iter,X,y):\n",
    "#     rdmsearch = RandomizedSearchCV(est, param_distributions=p_distr,\n",
    "#                                   n_jobs=-1, n_iter=nbr_iter, cv=9)\n",
    "#     #CV = Cross-Validation ( here using Stratified KFold CV)\n",
    "#     rdmsearch.fit(X,y)\n",
    "#     ht_params = rdmsearch.best_params_\n",
    "#     ht_score = rdmsearch.best_score_\n",
    "#     return ht_params, ht_score\n",
    "\n",
    "\n",
    "random_cv = RandomizedSearchCV(estimator=est,\n",
    "                              param_distributions=rf_p_dist,\n",
    "                              n_jobs=-1,n_iter=40,\n",
    "                              cv=5,scoring='neg_mean_absolute_error',verbose=5,\n",
    "                              return_train_score=True,random_state=40,\n",
    "                              iid=True)#Doing this to aboid warning as iid parameter default value will change from True to False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fitting 5 folds for each of 40 candidates, totalling 200 fits\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[Parallel(n_jobs=-1)]: Using backend LokyBackend with 4 concurrent workers.\n",
      "[Parallel(n_jobs=-1)]: Done  10 tasks      | elapsed:    4.1s\n",
      "[Parallel(n_jobs=-1)]: Done  64 tasks      | elapsed:   13.6s\n",
      "[Parallel(n_jobs=-1)]: Done 154 tasks      | elapsed:   26.4s\n",
      "[Parallel(n_jobs=-1)]: Done 200 out of 200 | elapsed:   35.7s finished\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " Time taken: 0 hours 0 minutes and 36.1 seconds.\n"
     ]
    }
   ],
   "source": [
    "# rf_parameters, rf_ht_score = hypertuning_rscv(est, rf_p_dist, 40, X, y)\n",
    "\n",
    "#To find execution time;here, we use variable random_cv\n",
    "from datetime import datetime #Only if we want to find the time\n",
    "# Here we go\n",
    "start_time = timer(None) # timing starts from this point for \"start_time\" variable\n",
    "random_cv.fit(X_train,y_train.values.ravel())\n",
    "timer(start_time) # timing ends here for \"start_time\" variable\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'bootstrap': True, 'criterion': 'entropy', 'max_depth': 3, 'max_features': 2, 'min_samples_leaf': 3, 'n_estimators': 300}\n",
      "-0.09333333333333334\n"
     ]
    }
   ],
   "source": [
    "# print(rf_parameters)\n",
    "# print(rf_ht_score)\n",
    "\n",
    "print(random_cv.best_params_)\n",
    "print(random_cv.best_score_)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, we are going to use the best parameters found by RandomizedSearchCV in model building..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "RandomForestClassifier(bootstrap=True, class_weight=None, criterion='entropy',\n",
       "                       max_depth=3, max_features=2, max_leaf_nodes=None,\n",
       "                       min_impurity_decrease=0.0, min_impurity_split=None,\n",
       "                       min_samples_leaf=3, min_samples_split=2,\n",
       "                       min_weight_fraction_leaf=0.0, n_estimators=300,\n",
       "                       n_jobs=None, oob_score=False, random_state=10, verbose=0,\n",
       "                       warm_start=False)"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "classifier = RandomForestClassifier(bootstrap=True,criterion='entropy',max_depth=3,max_features=2,min_samples_leaf=3,\n",
    "                                   n_estimators=300,random_state=10)\n",
    "classifier.fit(X_train,y_train.values.ravel())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = classifier.predict(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [],
   "source": [
    "cm = confusion_matrix(y_test,y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.94"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "accuracy = accuracy_score(y_test,y_pred)\n",
    "accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8973311444652907"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Cross_val_Score\n",
    "score = cross_val_score(classifier,X,y.values.ravel(),cv=10,scoring='accuracy').mean()\n",
    "score"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's now play with <h3>Xgboost Classifier</h3>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [],
   "source": [
    "from xgboost import XGBClassifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,\n",
       "              colsample_bynode=1, colsample_bytree=1, gamma=0,\n",
       "              learning_rate=0.1, max_delta_step=0, max_depth=3,\n",
       "              min_child_weight=1, missing=None, n_estimators=100, n_jobs=1,\n",
       "              nthread=None, objective='binary:logistic', random_state=40,\n",
       "              reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,\n",
       "              silent=None, subsample=1, verbosity=1)"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clf = XGBClassifier(random_state=40)\n",
    "clf.fit(X_train,y_train.values.ravel())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = clf.predict(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.metrics import confusion_matrix\n",
    "cm = confusion_matrix(y_test,y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.94"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "accuracy = accuracy_score(y_test,y_pred)\n",
    "accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8724203000468822"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#Cross_val_Score\n",
    "from sklearn.model_selection import cross_val_score\n",
    "score = cross_val_score(clf,X,y.values.ravel(),cv=5,scoring='accuracy').mean()\n",
    "score"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's play with hyperparameter tuning for Xgboost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import RandomizedSearchCV"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {},
   "outputs": [],
   "source": [
    "est = XGBClassifier(n_jobs=-1)\n",
    "rf_p_dist={'max_depth':[3,5,10,13,15],\n",
    "              'n_estimators':[10,100,200,300,400,500,600,700,800,900,1000],\n",
    "               'booster':['gbtree','gblinear','dart'],\n",
    "               'learning_rate':[0.05,0.1,0.15,0.2],\n",
    "               'base_score':[0.25,0.50,0.75,0.99],\n",
    "               'min_child_weight':[1,2,3,4,5],\n",
    "               'gamma':[0.0,0.1,0.2,0.3,0.4]\n",
    "              }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Use this function if you wanna execute via function otherwise use the variable\n",
    "# def hypertuning_rscv(est, p_distr, nbr_iter,X,y):\n",
    "#     rdmsearch = RandomizedSearchCV(est, param_distributions=p_distr,\n",
    "#                                   n_jobs=-1, n_iter=nbr_iter, cv=5)\n",
    "#     #CV = Cross-Validation ( here using Stratified KFold CV)\n",
    "#     rdmsearch.fit(X,y)\n",
    "#     ht_params = rdmsearch.best_params_\n",
    "#     ht_score = rdmsearch.best_score_\n",
    "#     return ht_params, ht_score\n",
    "\n",
    "\n",
    "\n",
    "random_cv = RandomizedSearchCV(estimator=est,\n",
    "                              param_distributions=rf_p_dist,\n",
    "                              n_jobs=-1,n_iter=40,\n",
    "                              cv=5,scoring='neg_mean_absolute_error',verbose=5,\n",
    "                              return_train_score=True,random_state=40,\n",
    "                              iid=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Fitting 5 folds for each of 40 candidates, totalling 200 fits\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[Parallel(n_jobs=-1)]: Using backend LokyBackend with 4 concurrent workers.\n",
      "[Parallel(n_jobs=-1)]: Done  10 tasks      | elapsed:    3.5s\n",
      "[Parallel(n_jobs=-1)]: Done  64 tasks      | elapsed:   21.9s\n",
      "[Parallel(n_jobs=-1)]: Done 154 tasks      | elapsed:  1.0min\n",
      "[Parallel(n_jobs=-1)]: Done 200 out of 200 | elapsed:  1.2min finished\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      " Time taken: 0 hours 1 minutes and 11.82 seconds.\n"
     ]
    }
   ],
   "source": [
    "#rf_parameters, rf_ht_score = hypertuning_rscv(est, rf_p_dist, 5, X, y)\n",
    "\n",
    "#To find execution time;here, we use variable random_cv\n",
    "from datetime import datetime #Only if we want to find the time\n",
    "# Here we go\n",
    "start_time = timer(None) # timing starts from this point for \"start_time\" variable\n",
    "random_cv.fit(X_train,y_train.values.ravel())\n",
    "timer(start_time) # timing ends here for \"start_time\" variable"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'n_estimators': 700, 'min_child_weight': 2, 'max_depth': 10, 'learning_rate': 0.15, 'gamma': 0.4, 'booster': 'gbtree', 'base_score': 0.99}\n",
      "-0.09666666666666666\n"
     ]
    }
   ],
   "source": [
    "# print(rf_parameters)\n",
    "# print(rf_ht_score)\n",
    "print(random_cv.best_params_)\n",
    "print(random_cv.best_score_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "XGBClassifier(base_score=0.99, booster='gbtree', colsample_bylevel=1,\n",
       "              colsample_bynode=1, colsample_bytree=1, cv=5, gamma=0.4,\n",
       "              learning_rate=0.15, max_delta_step=0, max_depth=10,\n",
       "              min_child_weight=2, missing=None, n_estimators=700, n_jobs=1,\n",
       "              nthread=None, objective='binary:logistic', random_state=0,\n",
       "              reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,\n",
       "              silent=None, subsample=1, verbosity=1)"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clf = XGBClassifier(n_estimators=700, min_child_weight=2, max_depth=10, learning_rate=0.15, gamma=0.4, booster = 'gbtree', base_score = 0.99,cv=5)\n",
    "clf.fit(X_train,y_train.values.ravel())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = clf.predict(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {},
   "outputs": [],
   "source": [
    "cm = confusion_matrix(y_test,y_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.94"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "accuracy = accuracy_score(y_test,y_pred)\n",
    "accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8975171982489055"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score = cross_val_score(clf,X,y.values.ravel(),cv=10,scoring='accuracy').mean()\n",
    "score.mean()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
